#include <stdio.h>
#include "string.h"
#include "iot_debug.h"
#include "iot_uart.h"
#include "iot_os.h"
#include "ats_config.h"

#include "uart_shell.h"
#include "shell/shell.h"
#include "shell/log.h"
#include "app_config.h"

void uartLogWriter(char* buffer, short len);
Shell shell;
HANDLE shell_thread = NULL;
char shell_buffer[512];
Log uartLog = {
  .write = uartLogWriter,
  .active = 1,
  .level = LOG_DEBUG
};

// port printf to uart usb
int my_printf(const char* fmt, ...)
{
  char line_buf[512];

  int len;
  va_list ap;

  va_start(ap, fmt);
  len = vsprintf(line_buf, fmt, ap);
  va_end(ap);

  return iot_uart_write(SHELL_UART_PORT, (uint8_t*)line_buf, len);
}

void shell_writer(const char word)
{
  iot_uart_write(SHELL_UART_PORT, (UINT8*)(&word), 1);
}

void uartLogWriter(char* buffer, short len)
{
  if(uartLog.shell) {
    shellWriteEndLine(uartLog.shell, buffer, len);
  }
}

void uart_msg_send(HANDLE hTask, TASK_MSG_ID id, void *param, UINT32 len)
{
  TASK_MSG *msg = NULL;

  msg = (TASK_MSG *)iot_os_malloc(sizeof(TASK_MSG));
  msg->id = id;
  msg->param = param;
  msg->len = len;

  iot_os_send_message(hTask, msg);
}

void push_cmd(const char* buf, int32_t length)
{
  char *recv_buff = NULL;
  recv_buff = iot_os_malloc(length);
  if(recv_buff == NULL) {
    iot_debug_print("uart_recv_handle_0 recv_buff malloc fail %d", length);
    return;
  }

  memcpy(recv_buff, buf, length);
  uart_msg_send(shell_thread, UART_RECV_MSG, recv_buff, length);
}

#if 0
void osiPanicInfoFuncLineSet(const char *func, int line)
{
  my_printf("ASSERT FAILED AT [%s] [%d]\r\n", func, line);
}
#else
void _assert(const char* f, int l)
{
  my_printf("ASSERT FAILED AT [%s] [%d]\r\n", f, l);
}
#endif

int get_sys_timestamp()
{
  // 获取为 5 ms，除2后得到10ms 为单位
  return OPENAT_get_system_tick() / 2;
}

//中断方式读串口1数据
//注: 中断中有复杂的逻辑,要发送消息到task中处理
void shell_uart_recv_handle(T_AMOPENAT_UART_MESSAGE* evt)
{
  char *recv_buff = NULL;
  int32 recv_len;
  int32 dataLen = evt->param.dataLen;
  if(!dataLen) {
    return;
  }

  recv_buff = iot_os_malloc(dataLen);
  if(recv_buff == NULL) {
    iot_debug_print("uart_recv_handle_0 recv_buff malloc fail %d", dataLen);
    return;
  }	
  switch(evt->evtId) {
    case OPENAT_DRV_EVT_UART_RX_DATA_IND:
      recv_len = iot_uart_read(SHELL_UART_PORT, (UINT8*)recv_buff, dataLen, SHELL_UART_RECV_TIMEOUT);
      iot_debug_print("shell uart recv length %d", recv_len);
      uart_msg_send(shell_thread, UART_RECV_MSG, recv_buff, recv_len);
      break;
    case OPENAT_DRV_EVT_UART_TX_DONE_IND:
      iot_debug_print("uart_recv_handle_2 OPENAT_DRV_EVT_UART_TX_DONE_IND");
      break;
    default:
      iot_debug_print("unknown event %d", evt->evtId);
      break;
  }
}

void shell_uart_open(PUART_MESSAGE handler)
{
  BOOL err;
  T_AMOPENAT_UART_PARAM uartCfg;
  
  memset(&uartCfg, 0, sizeof(T_AMOPENAT_UART_PARAM));
  uartCfg.baud = OPENAT_UART_BAUD_115200; //波特率
  uartCfg.dataBits = 8;   //数据位
  uartCfg.stopBits = 1; // 停止位
  uartCfg.parity = OPENAT_UART_NO_PARITY; // 无校验
  uartCfg.flowControl = OPENAT_UART_FLOWCONTROL_NONE; //无流控
  if(handler) {
    uartCfg.txDoneReport = TRUE; // 设置TURE可以在回调函数中收到OPENAT_DRV_EVT_UART_TX_DONE_IND
    uartCfg.uartMsgHande = handler; //回调函数
  } else {
    uartCfg.txDoneReport = FALSE;
    uartCfg.uartMsgHande = NULL; //回调函数
  }

  err = iot_uart_open(SHELL_UART_PORT, &uartCfg);
  iot_debug_print("[uart] shell uart_open err: %d", err);
}

void get_core_ver(char* core_ver, int size_max)
{
#define VER_TAIL "_RDA8910"
#define VER_PREFIX "CSDK_V"  
  char* pos = strstr(GMR_ID, VER_TAIL);
  if(!pos) {
    my_printf("cannot found version tail, failed.\r\n");
    return;
  }

  memset(core_ver, 0, size_max);
  int size = pos - GMR_ID - strlen(VER_PREFIX);
  memcpy(core_ver, GMR_ID + strlen(VER_PREFIX), size);
}

void shell_task_entry(void* params)
{  
  // 初始化命令行串口
  shell_uart_open(shell_uart_recv_handle);
  shell.read = NULL;
  shell.write = shell_writer;
  shellInit(&shell, shell_buffer, sizeof(shell_buffer));
  logRegister(&uartLog, &shell);

  char core_ver[8] = {0};
  get_core_ver(core_ver, sizeof(core_ver));
  my_printf("\r\nWelcome to espush core %s\r\n", core_ver);

	TASK_MSG *msg = NULL;
  while(1) {
    iot_os_wait_message(shell_thread, (PVOID*)&msg);
    switch(msg->id) {
      case UART_RECV_MSG:    
        iot_debug_print("[uart] uart_task_main_1 recv_len %d", msg->len);
        char* rcvData = msg->param;
        for(int i=0; i!=msg->len; ++i) {
          shellHandler(&shell, rcvData[i]);
        }
        break;
      default:
        break;
    }

    if(msg) {
      if(msg->param) {
        iot_os_free(msg->param);
        msg->param = NULL;
      }
      iot_os_free(msg);
      msg = NULL;
      iot_debug_print("[uart] uart_task_main_2 uart free");
    }
  }
}

void start_uart_shell()
{
  shell_thread = iot_os_create_task(shell_task_entry, NULL, 8192, THREAD_PRIORITY_SHELL, OPENAT_OS_CREATE_DEFAULT, "uart_task");
  if(!shell_thread) {
    my_printf("shell task start failed.\r\n");
  }
}
